// 7.5 构造函数再探
/**
 * 7.5.1 构造函数再探
 * 如果没有在构造函数的初始值列表中显式地初始化成员，则该成员将在构造函数体之前执行默认初始化。
 * 如果成员是const、引用，或者属于某种未提供默认构造函数的类类型，我们必须通过构造函数初始值列表为这些成员提供初值。
 * 建议：使用构造函数初始值。
 * 成员的初始化顺序与它们在类定义中的出现顺序一致：第一个成员先被初始化，然后第二个，以此类推。
 * 构造函数初始值列表中初始值的前后位置关系不会影响实际的初始化顺序。
 * 最好令构造函数初始值的顺序与成员声明的顺序保持一致。而且如果可能的话，尽量避免使用某些成员初始化其他成员。
 * 如果一个构造函数为所有参数都提供了默认实参，则它实际上也定义了默认构造函数。
 */

#include <iostream>
#include <vector>
#include "Sales_data.h"
//#include "Screen.h" // 难道是因为Window_mgr被声明成Screen的友元的原因？导致这个源文件同时包含这两个头文件时会导致一些问题？
#include "WindowMgr.h"
using std::cerr, std::clog;
using std::cin, std::cout, std::endl;

// 这段代码和我们在237页的原始定义效果是相同的：当构造函数完成后，数据成员的值相同。
// Sales_data构造函数的一种写法，虽然合法但比较草率，没有使用构造函数初始值（或构造函数初始值列表）
// Sales_data::Sales_data(const string &s,unsigned cnt, double price)
// {
//     bookNo = s;
//     units_sold = cnt;
//     revenue = cnt * price;
// }

// 构造函数的初始值有时必不可少，如果成员是const或者是引用的话，必须将其初始化。
// 类似的，当成员属于某种类类型且该类没有定义默认构造函数时，也必须将这个成员初始化。
class ConstRef
{
public:
    ConstRef(int ii);

private:
    int i;
    // 和其他常量对象或者引用一样，成员ci和ri都必须被初始化。
    // 如果我们没有为它们提供构造函数初始值的话将引发错误.
    const int ci;
    int &ri;
};

// 错误的构造函数
// ConstRef::ConstRef(int ii)
// {
//     i = ii;
//     ci = ii; // 错误，不能给const赋值
//     ri = i;  // 错误，ri未被初始化
// }

// 正确的构造函数
// 我们初始化const或者引用类型的数据成员的唯一机会就是通过构造函数初始值，因此该构造函数的正确形式应该是：
ConstRef::ConstRef(int ii) : i(ii), ci(ii), ri(i) {}

int main()
{

    return 0;
}